package com.abchina.test;

import com.alibaba.dubbo.common.utils.StringUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.IntFunction;
import java.util.stream.Stream;

/**
 * Created by cherry on 15/11/21.
 */
public class ZookeeperWrapper {
    public static final class Path {
        String[] pathNode;
        public Path(String path) {
            this(toPathNodes(path.trim()));
        }
        public Path(String[] pathNode) {
            if(pathNode==null) {
                throw new NullPointerException("路径不能为空");
            }
            this.pathNode = pathNode;
        }
        public Path getParent() {
            Path parent = null;
            if(pathNode.length>0)
                parent = new Path(Arrays.copyOf(pathNode,pathNode.length-1));
            return parent;
        }
        public String toString() {
            String ret = "/";
            for(int i=0;i<pathNode.length;i++) {
                if(i>0) ret += "/";
                ret += pathNode[i];
            }
            return ret;
        }

        public Path children(String child) {
            String[] childNode = new String[pathNode.length+1];
            System.arraycopy(pathNode,0,childNode,0,pathNode.length);
            childNode[childNode.length-1] = child;
            return new Path(childNode);
        }
    }
    protected final Map<String, ZookeeperNode> nodes;
    protected final ZooKeeper zk;
    private static final String TAG = "hehe";
    public ZookeeperWrapper(ZooKeeper zk) {
        this.zk = zk;
        this.nodes = new HashMap<String, ZookeeperNode>();
    }
    private final ZookeeperNode addIfnotPresent(Path path) {
        ZookeeperNode node = null;
        if(!nodes.containsKey(path)) {
            nodes.put(path.toString(), node = new ZookeeperNode(path.toString()));
        } else {
            node = nodes.get(path);
        }
        return node;
    }
    public final List<String> getChildren(Path path) {
        addIfnotPresent(path);
        List<String> children = new ArrayList<String>();
        try {
            children = zk.getChildren(path.toString(), false);
            for (String child:children) {

            }
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return children;
    }

    public final void create(Path path) {
        try {
            if(!exists(path))
                zk.create(path.toString(), null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public final void setData(Path path, String data) {
        if(!exists(path))
            create(path);
        try {
            zk.setData(path.toString(), data==null?null:data.getBytes(), -1);
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static final String[] toPathNodes(String path) {
        ArrayList<String> pathNodes = new ArrayList<String>();
        for(String pathNode:path.split("/")) {
            if(!pathNode.trim().isEmpty())
                pathNodes.add(pathNode.trim());
        }
        return pathNodes.toArray(new String[pathNodes.size()]);
    }

    private static final String toPath(String[] pathNodes) {
        String path = "";
        for(String pathNode:pathNodes) {
            path += "/"+pathNode;
        }
        return path;
    }

    public static void main(String[] args) {
        String path = "/dubbo/123/45/";
        System.err.println(toPath(toPathNodes(path)));
    }

    public final byte[] getData(Path path) {
        byte[] ret = null;
        try {
            ret = zk.getData(path.toString(), false, null);
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ret;
    }
    public final boolean exists(Path path) {
        boolean ret = false;
        try {
            ret = zk.exists(path.toString(), false) != null;
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ret;
    }
    public void showPath(Path path) {
        showPath(path, false);
    }
    public void showPath(Path path, boolean recursively) {
        if(exists(path)){
            System.err.print(path);
            byte[] dataBytes = getData(path);
            if(dataBytes!=null&&dataBytes.length>0)
                System.err.print("->"+new String(dataBytes));
            System.err.println();
            if(recursively) {
                List<String> children = getChildren(path);
                for (String child : children) {
//                    if(!path.endsWith("/"))path += "/";
                    showPath(path.children(child), recursively);

                }
            }
        } else {
            System.err.println(path+"不存在");
        }

    }
}
